package de.bht.mi.kriz.multitouch;

import java.util.HashMap;
import java.util.Map;

import org.metalev.multitouch.controller.MultiTouchController;
import org.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;
import org.metalev.multitouch.controller.MultiTouchController.PointInfo;
import org.metalev.multitouch.controller.MultiTouchController.PositionAndScale;

import de.bht.mi.kriz.multitouch.components.ContainerElement;
import de.bht.mi.kriz.multitouch.components.MultiTouchViewElement;

import android.content.Context;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

public class ContainerView extends RelativeLayout implements MultiTouchObjectCanvas<Object> {

	private MultiTouchController<Object> multiTouchController;
	private Map<Integer, Integer> touchMap = new HashMap<Integer, Integer>();
	
	public ContainerView(Context context) 
	{
		super(context);
		setWillNotDraw(false);
		
		ContainerElement container1 = new ContainerElement(context, 50, 50);
		container1.setWidth(200);
		container1.setHeight(150);
		container1.setTitle("Container 1");
		addView(container1);
		
		ContainerElement container2 = new ContainerElement(context, 50, 50);
		container2.setWidth(200);
		container2.setHeight(150);
		container2.setTitle("Container 2");
		container1.addView(container2);		
		
		ContainerElement container3 = new ContainerElement(context, 50, 50);
		container3.setWidth(200);
		container3.setHeight(150);
		container3.setTitle("Container 3");
		container2.addView(container3);		
		
		ContainerElement container4 = new ContainerElement(context, 50, 50);
		container4.setWidth(200);
		container4.setHeight(150);
		container4.setTitle("Container 4");
		container3.addView(container4);		
		
		ContainerElement container5 = new ContainerElement(context, 50, 50);
		container5.setWidth(200);
		container5.setHeight(150);
		container5.setTitle("Container 5");
		container4.addView(container5);				
		
		SquareElement square = new SquareElement(context, 20, 20);
		square.setWidth(80);
		square.setHeight(80);
		container5.addView(square);
		
		square = new SquareElement(context, 20, 20);
		square.setWidth(80);
		square.setHeight(80);
		container3.addView(square);		
		
		
		multiTouchController = new MultiTouchController<Object>(this);
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) 
	{
		return multiTouchController.onTouchEvent(event);
	}
	
	
	//iterates recursive through child views
	private Object recursiveChildSearchGetDraggable(Object object, PointInfo touchPoint)
	{
		if(object instanceof ViewGroup)
		{
			ViewGroup viewGroup = (ViewGroup) object;
			
			for(int i=0; i<viewGroup.getChildCount(); i++)
			{
				View viewGroupChild = viewGroup.getChildAt(i);
				
				if(viewGroupChild instanceof ViewGroup)
				{
					Object foundObject = recursiveChildSearchGetDraggable((ViewGroup) viewGroupChild, touchPoint);
					
					if(foundObject != this)
					{
						return foundObject;
					}
				}
				
				if(viewGroupChild instanceof MultiTouchViewElement)
				{
					MultiTouchViewElement cElement = (MultiTouchViewElement)viewGroupChild;
					int handlerCode = cElement.check(touchPoint.getX(), touchPoint.getY());
					if(handlerCode != MultiTouchViewElement.NONE && handlerCode != ContainerElement.CONTENT)
					{
						touchMap.put(touchPoint.getPointerIds()[touchPoint.getNumTouchPoints()], handlerCode);
						return cElement;
					}
				}
			}
		}
		return this;
	}
	
	private Object recursiveChildSearchGetContent(Object object, PointInfo touchPoint, Object notSelf)
	{
		if(object instanceof ViewGroup)
		{
			ViewGroup viewGroup = (ViewGroup) object;
			
			for(int i=0; i<viewGroup.getChildCount(); i++)
			{
				View viewGroupChild = viewGroup.getChildAt(i);
				
				if(viewGroupChild instanceof ViewGroup)
				{
					Object foundObject = recursiveChildSearchGetContent((ViewGroup) viewGroupChild, touchPoint, notSelf);
					
					if(foundObject != this && foundObject != notSelf)
					{
						return foundObject;
					}
				}
				
				if(viewGroupChild instanceof ContainerElement)
				{
					ContainerElement cElement = (ContainerElement)viewGroupChild;
					int handlerCode = cElement.check(touchPoint.getX(), touchPoint.getY());
					if(handlerCode == ContainerElement.CONTENT && cElement != notSelf) 
					{
						return cElement;
					}
				}
			}
		}
		return this;
	}	
	

	@Override
	public Object getDraggableObjectAtPoint(PointInfo touchPoint) 
	{
		return recursiveChildSearchGetDraggable(this, touchPoint);
	}

	@Override
	public void getPositionAndScale(Object obj, PositionAndScale objPosAndScaleOut) 
	{
		if(obj instanceof MultiTouchViewElement) 
		{
			MultiTouchViewElement v = (MultiTouchViewElement)obj;
			objPosAndScaleOut.set(v.getAbsolutePosition().x, v.getAbsolutePosition().y, false, 0, false, 0, 0, false, 0);
		}
		else
		{
		}
	}

	@Override
	public boolean setPositionAndScale(Object obj, PositionAndScale newObjPosAndScale, PointInfo touchPoint) 
	{
		int handlerCode = touchMap.get(touchPoint.getPointerIds()[touchPoint.getNumTouchPoints()]);
		
		if(obj instanceof ContainerElement) 
		{
			ContainerElement v = (ContainerElement)obj;
			
			switch(handlerCode)
			{
				case ContainerElement.SCALE_HANDLE_LEFT:
					Log.d("BOTTOM_CORNER_LEFT", touchPoint.getX()+":"+touchPoint.getY());
					v.setBottomLeftCorner((int)touchPoint.getX(), (int)touchPoint.getY());
					v.invalidate();
					break;
					
				case ContainerElement.SCALE_HANDLE_RIGHT:
					Log.d("BOTTOM_CORNER_RIGHT", touchPoint.getX()+":"+touchPoint.getY());
					v.setBottomRightCorner((int)touchPoint.getX(), (int)touchPoint.getY());
					v.invalidate();
					break;
			}
		}
		if(obj instanceof MultiTouchViewElement)
		{
			MultiTouchViewElement v = (MultiTouchViewElement) obj;
			
			switch(handlerCode)
			{
				case MultiTouchViewElement.MOVE_HANDLE:
					
					Point newGlobalPos = new Point((int)newObjPosAndScale.getXOff(), (int)newObjPosAndScale.getYOff());

					//search for other Element under TouchPoint
					Object o = recursiveChildSearchGetContent(this, touchPoint, v);
					if(o != null)
					{
						ViewGroup oldParent = (ViewGroup) v.getParent();
						ViewGroup newParent = (ViewGroup) o;
						
						if(oldParent != newParent)
						{
							if(oldParent instanceof ViewGroup)
							{
								oldParent.removeView(v);
								
							}
							if(oldParent instanceof MultiTouchViewElement)
							{
								((MultiTouchViewElement) oldParent).setAlpha(255);
							}
							
							newParent.addView(v);
							if(newParent instanceof MultiTouchViewElement)
							{
								((MultiTouchViewElement) newParent).setAlpha(120);
							}
						}
					}
					v.setGlobalPosition(newGlobalPos);
					Log.d("SET GLOBAL STUFF", "tp:"+touchPoint.getX()+":"+touchPoint.getY()+" "+newObjPosAndScale.getXOff()+":"+newObjPosAndScale.getYOff());
					
					v.invalidate();
					break;
			}
		}
		else
		{
			Log.d("NO ELEMENT HIT", newObjPosAndScale.getXOff()+":"+newObjPosAndScale.getYOff());
		}
		return false;
	}

	@Override
	public void selectObject(Object obj, PointInfo touchPoint) {
		//no more touchpoints
		if(obj == null) 
		{
			resetAlpha(this);
		}
	}

	//resets alpha values of all contained MultiTouchViewElement(s)
	private void resetAlpha(ViewGroup containerView) {
		
		if(containerView instanceof MultiTouchViewElement)
		{
			((MultiTouchViewElement) containerView).setAlpha(255);
			containerView.invalidate();
		}
		
		for(int i=0; i<containerView.getChildCount(); i++)
		{
			if(containerView.getChildAt(i) instanceof ViewGroup)
			{
				resetAlpha((ViewGroup) containerView.getChildAt(i));
			}
		}
		return;
		
	}


}
